/*
-----------------------------------------------------------------------------
This source file is part of DIVA
The project of Engineering Lab, dept. of CSIE, NTNU.

Copyright (c) 2000-2006 The Software Engineering Lab, dept. of CSIE, NTNU.
-----------------------------------------------------------------------------
Filename:	DIVA_InputManager.h 
			(Origin from http://www.ogre3d.org/wiki/index.php/Using_OIS)

Date:	2007/3/29

Description: 
			This class managed all mouse,keyboard event.
			We draw a simple flow below to explain:
			 
	[Device Event]------->InputManager--------->sent message to  classes implement some mouse/key actions
		        (captured every frame loop)

	If you've written some java ActionListener,I have to declare there's some difference here,just a very small difference
	In JAVA: 
		AWT.addActionListener(an actionlistener); //AWT will check input event here
	---------------
	Here(OIS):
		Device d = OIS::inputManager.createDevice(...);
		d.setEventCallBack(ActionListener);//Device will call ActionListener when Device capture any Input.
		.....
		.....
		for(;;){
			//Device should keep capture if there's anything input,if there is,Device will call ActionListener we setEventCallBack() above.
			d.capture();
		}

------------------------------------------------------------------------------
*/
#ifndef _DIVA_InputManager_H_
#define _DIVA_InputManager_H_


#include <OIS/OIS.h>
#include <OgreRenderWindow.h>

class DIVA_InputManager : public OIS::KeyListener, public OIS::MouseListener, public OIS::JoyStickListener {
public:
    virtual ~DIVA_InputManager( void );

    void initialise( Ogre::RenderWindow *renderWindow );
    void capture( void );

    void addKeyListener( OIS::KeyListener *keyListener, const std::string& instanceName );
    void addMouseListener( OIS::MouseListener *mouseListener, const std::string& instanceName );
    void addJoystickListener( OIS::JoyStickListener *joystickListener, const std::string& instanceName );

    void removeKeyListener( const std::string& instanceName );
    void removeMouseListener( const std::string& instanceName );
    void removeJoystickListener( const std::string& instanceName );

    void removeKeyListener( OIS::KeyListener *keyListener );
    void removeMouseListener( OIS::MouseListener *mouseListener );
    void removeJoystickListener( OIS::JoyStickListener *joystickListener );

    void removeAllListeners( void );
    void removeAllKeyListeners( void );
    void removeAllMouseListeners( void );
    void removeAllJoystickListeners( void );

	void  disableKeyListener( const std::string& instanceName );
	void  disableMouseListener( const std::string& instanceName );
	void  disableJoyStickListener( const std::string& instanceName );
	void  enableKeyListener( const std::string& instanceName );
	void  enableMouseListener( const std::string& instanceName ) ;
	void  enableJoyStickListener( const std::string& instanceName ) ;



    void setWindowExtents( int width, int height );

    OIS::Mouse*    getMouse( void );
    OIS::Keyboard* getKeyboard( void );
    OIS::JoyStick* getJoystick( unsigned int index );

    int getNumOfJoysticks( void );

    static DIVA_InputManager* getSingletonPtr( void );

	//** add by Cmj - 2007/04/04
	//** This method is for checking if any key, mouse or joyStick event is still executing,
	//** And make these events continously execute.
	void eventContinue( void );

private:
	static DIVA_InputManager *mInputManager;
    DIVA_InputManager( void );
    DIVA_InputManager( const DIVA_InputManager& ) { }
    DIVA_InputManager & operator = ( const DIVA_InputManager& );

    bool keyPressed( const OIS::KeyEvent &e );
    bool keyReleased( const OIS::KeyEvent &e );

    bool mouseMoved( const OIS::MouseEvent &e );
    bool mousePressed( const OIS::MouseEvent &e, OIS::MouseButtonID id );
    bool mouseReleased( const OIS::MouseEvent &e, OIS::MouseButtonID id );

    bool povMoved( const OIS::JoyStickEvent &e, int pov );
    bool axisMoved( const OIS::JoyStickEvent &e, int axis );
    bool sliderMoved( const OIS::JoyStickEvent &e, int sliderID );
    bool buttonPressed( const OIS::JoyStickEvent &e, int button );
    bool buttonReleased( const OIS::JoyStickEvent &e, int button );

    OIS::InputManager *mInputSystem;
    OIS::Mouse        *mMouse;
    OIS::Keyboard     *mKeyboard;

    std::vector<OIS::JoyStick*> mJoysticks;
    std::vector<OIS::JoyStick*>::iterator itJoystick;
    std::vector<OIS::JoyStick*>::iterator itJoystickEnd;

    std::map<std::string, OIS::KeyListener*> mKeyListeners;
    std::map<std::string, OIS::MouseListener*> mMouseListeners;
    std::map<std::string, OIS::JoyStickListener*> mJoystickListeners;

    std::map<std::string, OIS::KeyListener*>::iterator itKeyListener;
    std::map<std::string, OIS::MouseListener*>::iterator itMouseListener;
    std::map<std::string, OIS::JoyStickListener*>::iterator itJoystickListener;

    std::map<std::string, OIS::KeyListener*>::iterator itKeyListenerEnd;
    std::map<std::string, OIS::MouseListener*>::iterator itMouseListenerEnd;
    std::map<std::string, OIS::JoyStickListener*>::iterator itJoystickListenerEnd;

	std::map<std::string, bool> enKeyListeners ;
	std::map<std::string, bool> enMouseListeners ;
	std::map<std::string, bool> enJoystickListeners ;

	//** create of the using of the method eventContinue() - by Cmj 2007/04/05
	std::map< OIS::KeyListener* , const OIS::KeyEvent > keyEventCont;
	std::map< OIS::MouseListener*, const OIS::MouseEvent> mouseEventCont;
	std::map< OIS::JoyStickListener*, const OIS::JoyStickEvent > joyStickEventCont;

	std::map< OIS::KeyListener* , const OIS::KeyEvent >::iterator itKeyEvent;
	std::map< OIS::MouseListener*, const OIS::MouseEvent>::iterator itMouseEvent;
	std::map< OIS::JoyStickListener*, const OIS::JoyStickEvent >::iterator itJoyStickEvent;

	std::map< OIS::KeyListener* , const OIS::KeyEvent >::iterator itKeyEventEnd;
	std::map< OIS::MouseListener*, const OIS::MouseEvent>::iterator itMouseEventEnd;
	std::map< OIS::JoyStickListener*, const OIS::JoyStickEvent >::iterator itJoyStickEventEnd;
	//** ======================================================================================

    
};
#endif
